#include "rtda/heap/method.h"
#include "classfile/class_file.hpp"

namespace jvm {
namespace heap {

Method::Method(std::shared_ptr<Class> pClass, const std::shared_ptr<classfile::MemberInfo> pMemberInfo) {
    m_pClass = pClass;
    copyMemberInfo(pMemberInfo);
    copyAttributes(pMemberInfo);
}

std::vector<std::shared_ptr<Method>> Method::newMethods(std::shared_ptr<Class> pClass, const std::vector<std::shared_ptr<classfile::MemberInfo>>& cfMethods) {
    std::vector<std::shared_ptr<Method>> methods;
    methods.reserve(cfMethods.size());
    
    for (const auto& pMemberInfo : cfMethods) {
        methods.push_back(new Method(pClass, pMemberInfo));
    }
    
    return methods;
}

void Method::copyAttributes(const std::shared_ptr<classfile::MemberInfo> pMemberInfo) {
    if (auto pCodeAttr = pMemberInfo->getCodeAttribute()) {
        m_maxStack = pCodeAttr->getMaxStack();
        m_maxLocals = pCodeAttr->getMaxLocals();
        m_code = pCodeAttr->getCode();
    }
}

bool Method::isSynchronized() const { return 0 != (m_accessFlags & ACC_SYNCHRONIZED); }
bool Method::isBridge() const { return 0 != (m_accessFlags & ACC_BRIDGE); }
bool Method::isVarargs() const { return 0 != (m_accessFlags & ACC_VARARGS); }
bool Method::isNative() const { return 0 != (m_accessFlags & ACC_NATIVE); }
bool Method::isAbstract() const { return 0 != (m_accessFlags & ACC_ABSTRACT); }
bool Method::isStrict() const { return 0 != (m_accessFlags & ACC_STRICT); }

uint Method::getMaxStack() const { return m_maxStack; }
uint Method::getMaxLocals() const { return m_maxLocals; }
const std::vector<uint8_t>& Method::getCode() const { return m_code; }

} // namespace heap
} // namespace jvm